#ifndef _EMAC_INTERNAL_H_
#define _EMAC_INTERNAL_H_

#include "types.h"

#define EMAC_CONTROL_MODULE_BASE     0x01E22000 

#define REVID_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x00))
#define SOFTRESET_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x04))
#define INTCONTROL_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x0C))
#define C0RXTHRESHEN_REG		*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x10))
#define C0RXEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x14))
#define C0TXEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x18))
#define C0MISCEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x1C))
#define C1RXTHRESHEN_REG		*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x20))
#define C1RXEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x24))
#define C1TXEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x28))
#define C1MISCEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x2C))
#define C2RXTHRESHEN_REG		*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x30))
#define C2RXEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x34))
#define C2TXEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x38))
#define C2MISCEN_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x3C))
#define C0RXTHRESHSTAT_REG		*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x40))
#define C0RXSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x44))
#define C0TXSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x48))
#define C0MISCSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x4C))
#define C1RXTHRESHSTAT_REG		*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x50))
#define C1RXSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x54))
#define C1TXSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x58))
#define C1MISCSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x5C))
#define C2RXTHRESHSTAT_REG		*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x60))
#define C2RXSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x64))
#define C2TXSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x68))
#define C2MISCSTAT_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x6C))
#define C0RXIMAX_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x70))
#define C0TXIMAX_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x74))
#define C1RXIMAX_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x78))
#define C1TXIMAX_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x7C))
#define C2RXIMAX_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x80))
#define C2TXIMAX_REG			*((uint32_t *)(EMAC_CONTROL_MODULE_BASE + 0x84))

#define EMAC_REGISTERS_BASE 0x01E23000

#define TXREV_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x00))
#define TXCONTROL_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x04))
#define TXTEARDOWN_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x08))
#define RXREV_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x10))
#define RXCONTROL_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x14))
#define RXTEARDOWN_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x18))
#define TXINTSTATRAW_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x80))
#define TXINTSTATMASKED_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x84))
#define TXINTMASKSET_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x88))
#define TXINTMASKCLEAR_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x8c))
#define MACINVECTOR_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x90))
#define MACEOIVECTOR_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x94))
#define RXINTSTATRAW_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xa0))
#define RXINTSTATMASKED_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xa4))
#define RXINTMASKSET_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xa8))
#define RXINTMASKCLEAR_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xac))
#define MACINTSTATRAW_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xb0))
#define MACINTSTATMASKED_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xb4))
#define MACINTMASKSET_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xb8))
#define MACINTMASKCLEAR_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0xbc))
#define RXMBPENABLE_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x100))
#define RXUNICASTSET_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x104))
#define RXUNICASTCLEAR_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x108))
#define RXMAXLEN_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x10c))
#define RXBUFFEROFFSET_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x110))
#define RXFILTERLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x114))
#define RX0FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x120))
#define RX1FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x124))
#define RX2FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x128))
#define RX3FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x12c))
#define RX4FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x130))
#define RX5FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x134))
#define RX6FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x138))
#define RX7FLOWTHRESH_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x13c))
#define RX0FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x140))
#define RX1FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x144))
#define RX2FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x148))
#define RX3FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x14c))
#define RX4FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x150))
#define RX5FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x154))
#define RX6FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x158))
#define RX7FREEBUFFER_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x15c))
#define MACCONTROL_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x160))
#define MACSTATUS_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x164))
#define EMCONTROL_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x168))
#define FIFOCONTROL_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x16c))
#define MACCONFIG_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x170))
#define EMAC_SOFTRESET_REG			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x174))
#define MACSRCADDRLO_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1d0))
#define MACSRCADDRHI_REG 			*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1d4))
#define MACHASH1_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1d8))
#define MACHASH2_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1dc))
#define BOFFTEST_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1e0))
#define TPACETEST_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1e4))
#define RXPAUSE_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1e8))
#define TXPAUSE_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x1ec))
#define MACADDRLO_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x500))
#define MACADDRHI_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x504))
#define MACINDEX_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x508))
#define TX0HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x600))
#define TX1HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x604))
#define TX2HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x608))
#define TX3HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x60c))
#define TX4HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x610))
#define TX5HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x614))
#define TX6HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x618))
#define TX7HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x61c))
#define RX0HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x620))
#define RX1HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x624))
#define RX2HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x628))
#define RX3HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x62c))
#define RX4HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x630))
#define RX5HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x634))
#define RX6HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x638))
#define RX7HDP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x63c))
#define TX0CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x640))
#define TX1CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x644))
#define TX2CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x648))
#define TX3CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x64c))
#define TX4CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x650))
#define TX5CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x654))
#define TX6CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x658))
#define TX7CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x65c))
#define RX0CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x660))
#define RX1CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x664))
#define RX2CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x668))
#define RX3CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x66c))
#define RX4CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x670))
#define RX5CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x674))
#define RX6CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x678))
#define RX7CP_REG 				*((uint32_t *)(EMAC_REGISTERS_BASE + 0x67c))

#define EMAC_STATS_BASE 0x01E23200

#define RXGOODFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x00))
#define RXBCASTFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x04))
#define RXMCASTFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x08))
#define RXPAUSEFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x0c))
#define RXCRCERRORS_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x10))
#define RXALIGNCODEERRORS_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x14))
#define RXOVERSIZED_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x18))
#define RXJABBER_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x1c))
#define RXUNDERSIZED_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x20))
#define RXFRAGMENTS_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x24))
#define RXFILTERED_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x28))
#define RXQOSFILTERED_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x2c))
#define RXOCTETS_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x30))
#define TXGOODFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x34))
#define TXBCASTFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x38))
#define TXMCASTFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x3c))
#define TXPAUSEFRAMES_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x40))
#define TXDEFERRED_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x44))
#define TXCOLLISION_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x48))
#define TXSINGLECOLL_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x4c))
#define TXMULTICOLL_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x50))
#define TXEXCESSIVECOLL_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x54))
#define TXLATECOLL_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x58))
#define TXUNDERRUN_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x5c))
#define TXCARRIERSENSE_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x60))
#define TXOCTETS_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x64))
#define FRAME64_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x68))
#define FRAME65T127_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x6c))
#define FRAME128T255_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x70))
#define FRAME256T511_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x74))
#define FRAME512T1023_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x78))
#define FRAME1024TUP_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x7c))
#define NETOCTETS_REG				*((uint32_t *)(EMAC_STATS_BASE + 0x80))
#define RXSOFOVERRUNS_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x84))
#define RXMOFOVERRUNS_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x88))
#define RXDMAOVERRUNS_REG			*((uint32_t *)(EMAC_STATS_BASE + 0x8c))
#define EMAC_STATS_REGS				0x24


#define NUM_RX_BUFFERS 256
#define RX_LOW_THRESH  64  // Interrupt triggered if RX free-count drops

#define NUM_TX_BUFFERS 256
#define BUFFER_LEN     1500 // bytes


#define RX_DESC_MEM_BASE  0x01E20000
#define TX_DESC_MEM_BASE  0x01E21000



/*
* Descriptor flags
*/
#define EMAC_DSC_FLAG_SOP 0x8000
#define EMAC_DSC_FLAG_EOP 0x4000
#define EMAC_DSC_FLAG_OWNER 0x2000   // if set => owned by emac
#define EMAC_DSC_FLAG_EOQ 0x1000
#define EMAC_DSC_FLAG_TDOWNCMPLT 0x0800 
#define EMAC_DSC_FLAG_PASSCRC 0x0400  // if set => CRC already present in payload

/* RX desc flags */
#define EMAC_DSC_FLAG_JABBER 0x0200
#define EMAC_DSC_FLAG_OVERSIZE 0x0100
#define EMAC_DSC_FLAG_FRAGMENT 0x0080
#define EMAC_DSC_FLAG_UNDERSIZED 0x0040
#define EMAC_DSC_FLAG_CONTROL 0x0020
#define EMAC_DSC_FLAG_OVERRUN 0x0010
#define EMAC_DSC_FLAG_CODEERROR 0x0008
#define EMAC_DSC_FLAG_ALIGNERROR 0x0004
#define EMAC_DSC_FLAG_CRCERROR 0x0002
#define EMAC_DSC_FLAG_NOMATCH 0x0001

#define EMAC_DSC_ERR (EMAC_DSC_FLAG_OVERSIZE | EMAC_DSC_FLAG_JABBER | \
       EMAC_DSC_FLAG_FRAGMENT | EMAC_DSC_FLAG_UNDERSIZED | EMAC_DSC_FLAG_CONTROL | \
       EMAC_DSC_FLAG_OVERRUN | EMAC_DSC_FLAG_CODEERROR | EMAC_DSC_FLAG_ALIGNERROR | \
       EMAC_DSC_FLAG_NOMATCH | EMAC_DSC_FLAG_CRCERROR)

#define DESC_OWNED_BY_EMAC(desc)  ((desc)->flags & EMAC_DSC_FLAG_OWNER)
#define SOP_BUFFER(desc)  ((desc)->flags & EMAC_DSC_FLAG_SOP)
#define EOP_BUFFER(desc)  ((desc)->flags & EMAC_DSC_FLAG_EOP)
#define RX_BUFFER_ERR(desc) ((desc)->flags & EMAC_DSC_ERR)

typedef struct pkt_desc_t
{
   struct pkt_desc_t *next_ptr;  // next descriptor in chain
   uint8_t    *buf_ptr;

   uint16_t   buf_len;
   uint16_t   buf_offset;
   uint16_t   packet_len;  // applicable only for SOP buffers
   uint16_t   flags;
}pkt_desc_t;

#endif
